#include <stdio.h>
#include <string.h>
#include <omnetpp.h>
#include "MyMsg_m.h"

#define NodeNum 6

using namespace omnetpp;

class NodeDSDV : public cSimpleModule
{
public:
    int myRouteTable[6][6][4] =
           {{{0,0,0,8},{1,2,2,8},{2,2,1,8},{3,2,2,8},{4,2,3,8},{5,2,3,8}},
            {{0,2,2,8},{1,1,0,8},{2,2,1,8},{3,2,2,8},{4,2,3,8},{5,2,3,8}},
            {{0,0,1,8},{1,1,1,8},{2,2,0,8},{3,3,1,8},{4,3,2,8},{5,3,2,8}},
            {{0,2,2,8},{1,2,2,8},{2,2,1,8},{3,3,0,8},{4,4,1,8},{5,5,1,8}},
            {{0,3,3,8},{1,3,3,8},{2,3,2,8},{3,3,1,8},{4,4,0,8},{5,3,2,8}},
            {{0,3,3,8},{1,3,3,8},{2,3,2,8},{3,3,1,8},{4,3,2,8},{5,5,0,8}}};

private:
    simsignal_t arrivalSignal;

protected:
    virtual MyMsg *generateMessage();
    virtual void forwardMessage(MyMsg *msg);
    virtual void initialize() override;
    virtual void handleMessage(cMessage *msg) override;
};

Define_Module(NodeDSDV);

void NodeDSDV::initialize()
{
    arrivalSignal = registerSignal("arrival");

    if(getIndex() == 0)
    {
        MyMsg *msg = generateMessage();
        scheduleAt(0.0 , msg);
    }
}

void NodeDSDV::handleMessage(cMessage *msg)
{
    MyMsg *ttmsg = check_and_cast<MyMsg *>(msg);

    if(ttmsg->getDestination() == getIndex())
    {
        int hopcount = ttmsg->getHopCount();
        emit(arrivalSignal,hopcount);

        EV << "Message " << ttmsg << " arrived after " << hopcount << "hops.\n";
        bubble("ARRIVED, starting new one!");

        delete ttmsg;

        EV << "Generating another message: ";
        MyMsg *newmsg = generateMessage();
        EV << newmsg << endl;
        forwardMessage(newmsg);
    }
    else if(ttmsg->getNext() == getIndex())
    {
        forwardMessage(ttmsg);
    }
    else
    {
        delete ttmsg;
    }
}

MyMsg *NodeDSDV::generateMessage()
{
    int src = getIndex();
    int n = getVectorSize();
    int dest = intuniform(0 , n-2);
    if(dest >= src)
        dest++;

    char msgname[20];
    sprintf(msgname,"src-%d-dst-%d",src,dest);

    MyMsg *msg = new MyMsg(msgname);
    msg->setSource(src);
    msg->setDestination(dest);
    return msg;
}

void NodeDSDV::forwardMessage(MyMsg *msg)
{
    MyMsg *copymsg;
    msg->setHopCount(msg->getHopCount()+1);

    int n = myRouteTable[getIndex()][msg->getDestination()][1];
    msg->setNext(n);
    int k = gateSize("gate");
    int index = getIndex();

    for(int i=0;i<k;i++)
    {
        copymsg = msg->dup();
        EV << "Forwarding message " << msg << " on node["<< index << "] gate[" << i << "]\n";
        send(copymsg , "gate$o" , i);
    }
    delete msg;
}
